//----------------------------------Include-------------------------------------
#include <stdint.h>
#include "mcu.h"
#include "glbvar.h"
#include "ch395.h"
//------------------------------------------------------------------------------

//-----------------------------------Macro--------------------------------------
#define _tx_data(p, l)            do{ mcu_uart6_dma_tx((char*)p, l); }while(0)
#define _Query395Interrupt()      mcu_get_eth_int()
//------------------------------------------------------------------------------

//-----------------------------------Types--------------------------------------
//------------------------------------------------------------------------------

//---------------------------------Static Var-----------------------------------
static char ntxbuf[64];
//------------------------------------------------------------------------------
//ip
struct _CH395_SYS CH395Inf;
const UINT8 CH395IPAddr[4]   = {192, 168, 1, 201}; /* CH395 IP  */
const UINT8 CH395GWIPAddr[4] = {192, 168, 1, 1  }; /* CH395 gateway */
const UINT8 CH395IPMask[4]   = {255, 255, 255, 0}; /* CH395 mask */
//------------------------------------------------------------------------------
//socket
struct _SOCK_INF SockInf[1];
const UINT8  Socket0DesIP[4] = {255, 255, 255, 255};
const UINT16 Socket0DesPort  = 1000;
const UINT16 Socket0SourPort = 5000;
//------------------------------------------------------------------------------
UINT8 sock_int_status[8] = {
    SINT_STAT_SENDBUF_FREE,
    SINT_STAT_SENDBUF_FREE,
    SINT_STAT_SENDBUF_FREE,
    SINT_STAT_SENDBUF_FREE,
    SINT_STAT_SENDBUF_FREE,
    SINT_STAT_SENDBUF_FREE,
    SINT_STAT_SENDBUF_FREE,
    SINT_STAT_SENDBUF_FREE,
};
//------------------------------------------------------------------------------
UINT8 MyBuffer[1][2048]; /* data buffer */

/*By default, each of the first four sockets is allocated 4 buffer blocks (2048 bytes each) for the send buffer.
If needed, the receive and send buffers can be reallocated using the CMD_SET_RECV_BUF and CMD_SET_SEND_BUF commands.*/
UINT16 SocketSendBufferSizes[8] = {
    2048,
    2048,
    2048,
    2048,
    0,
    0,
    0,
    0,
};
UINT16 Recv_len[1];
//------------------------------------------------------------------------------

//--------------------------------Static Func-----------------------------------
static void _InitCH395InfParam(void)
{
  memset(&CH395Inf, 0, sizeof(CH395Inf));                          /* Clear all CH395Inf to zero */
  memcpy(CH395Inf.IPAddr,   CH395IPAddr,   sizeof(CH395IPAddr));   /* Enter the IP address in the CH395Inf file */
  memcpy(CH395Inf.GWIPAddr, CH395GWIPAddr, sizeof(CH395GWIPAddr)); /* Enter the gateway IP address in the CH395Inf file */
  memcpy(CH395Inf.MASKAddr, CH395IPMask,   sizeof(CH395IPMask));   /* Enter the mask IP address in the CH395Inf file */
}
//------------------------------------------------------------------------------
static void _InitSocketParam(void)
{
  memset(&SockInf[0], 0, sizeof(SockInf[0]));                    /* Clear all fields of SockInf[0] */
  memcpy(SockInf[0].IPAddr, Socket0DesIP, sizeof(Socket0DesIP)); /* Write destination IP address */
  SockInf[0].DesPort   = Socket0DesPort;                         /* Destination port */
  SockInf[0].SourPort  = Socket0SourPort;                        /* Source port */
  SockInf[0].ProtoType = PROTO_TYPE_UDP;                         /* UDP mode */
}

static void _SocketInitOpen(void)
{
  UINT8 i;
  /* Socket 0 in UDP mode */
  CH395CMDSetSocketDesIP(0, SockInf[0].IPAddr);       /* Set destination IP address for socket 0 */
  CH395CMDSetSocketProtType(0, SockInf[0].ProtoType); /* Set protocol type for socket 0 */
  CH395CMDSetSocketDesPort(0, SockInf[0].DesPort);    /* Set destination port for socket 0 */
  CH395CMDSetSocketSourPort(0, SockInf[0].SourPort);  /* Set source port for socket 0 */
  i = CH395CMDOpenSocket(0);                          /* Open socket 0 */
  //mStopIfError(i);
}
//------------------------------------------------------------------------------
void CH395SocketInterrupt(UINT8 sockindex)
{
  sock_int_status[sockindex] |= CH395CMDGetSocketInt(sockindex); /* Gets the socket interrupt status */

  if(sock_int_status[sockindex] & SINT_STAT_RECV){ /* Receive interruption */
    // Handle it in the main program
  }
  if(sock_int_status[sockindex] & SINT_STAT_SENDBUF_FREE){ /* The send buffer is free and can continue writing data to be sent */
    // Handle it in the main program
  }
  if(sock_int_status[sockindex] & SINT_STAT_SEND_OK){ /* Send completion interrupt */
    sock_int_status[sockindex] &= ~SINT_STAT_SEND_OK;
  }
  if(sock_int_status[sockindex] & SINT_STAT_CONNECT){ /* The connection is interrupted, valid only in TCP mode */
    sock_int_status[sockindex] &= ~SINT_STAT_CONNECT;
    //printf("SINT_STAT_CONNECT\r\n");
  }
  if(sock_int_status[sockindex] & SINT_STAT_DISCONNECT){ /* Disconnect interrupt, valid only in TCP mode */
    sock_int_status[sockindex] &= ~SINT_STAT_DISCONNECT;
    //printf("SINT_STAT_DISCONNECT \r\n");
  }
  if(sock_int_status[sockindex] & SINT_STAT_TIM_OUT){ /* Timeout interrupt, valid only in TCP mode */
    sock_int_status[sockindex] &= ~SINT_STAT_TIM_OUT;
    //printf("SINT_STAT_TIM_OUT\r\n");
  }
}

void CH395GlobalInterrupt(void)
{
  UINT16 init_status;
  
  init_status = CH395CMDGetGlobIntStatus();

  if(init_status & GINT_STAT_UNREACH)  {} /* Unreachable interrupt,to read unreachable information */
  if(init_status & GINT_STAT_IP_CONFLI){} /* IP address conflict interrupted,advice to change the IP address of the CH395 again and initialize the CH395 */
  if(init_status & GINT_STAT_PHY_CHANGE){ /* PHY change interrupt */
    //printf("Init status : GINT_STAT_PHY_CHANGE\r\n");
  }
  if(init_status & GINT_STAT_DHCP){}
  if(init_status & GINT_STAT_SOCK0){
    CH395SocketInterrupt(0); /* socket 0 interrupt */
  }
  if(init_status & GINT_STAT_SOCK1){
    CH395SocketInterrupt(1); /* socket 1 interrupt */
  }
  if(init_status & GINT_STAT_SOCK2){
    CH395SocketInterrupt(2); /* socket 2 interrupt */
  }
  if(init_status & GINT_STAT_SOCK3){
    CH395SocketInterrupt(3); /* socket 3 interrupt */
  }
  if(init_status & GINT_STAT_SOCK4){
    CH395SocketInterrupt(4); /* socket 4 interrupt */
  }
  if(init_status & GINT_STAT_SOCK5){
    CH395SocketInterrupt(5); /* socket 5 interrupt */
  }
  if(init_status & GINT_STAT_SOCK6){
    CH395SocketInterrupt(6); /* socket 6 interrupt */
  }
  if(init_status & GINT_STAT_SOCK7){
    CH395SocketInterrupt(7); /* socket 7 interrupt */
  }
}
//------------------------------------------------------------------------------
void UDP_Server_Data_Loop(UINT8 sockindex)
{
  u16 port;
  if (Recv_len[sockindex] == 0){
    if (sock_int_status[sockindex] & SINT_STAT_RECV){
      sock_int_status[sockindex] &= ~SINT_STAT_RECV;
      Recv_len[sockindex] = CH395CMDGetRecvLength(sockindex); /* Gets the length of data in the current buffer */
      CH395CMDGetRecvData(sockindex, Recv_len[sockindex], MyBuffer[sockindex]);
      port = ((UINT16)MyBuffer[sockindex][3] << 8) + MyBuffer[sockindex][2];
      //printf("Socket %d receive len : %d\r\n", sockindex, Recv_len[sockindex]);
      //printf("Port = %d\n", port);
      //printf("IP = %2d.%2d.%2d.%2d.\n", (UINT16)MyBuffer[sockindex][4], (UINT16)MyBuffer[sockindex][5], (UINT16)MyBuffer[sockindex][6], (UINT16)MyBuffer[sockindex][7]);
    }
  }else{
    if (sock_int_status[sockindex] & SINT_STAT_SENDBUF_FREE){
      sock_int_status[sockindex] &= ~SINT_STAT_SENDBUF_FREE;
      port = ((UINT16)MyBuffer[sockindex][3] << 8) + MyBuffer[sockindex][2];
      CH395UDPSendTo(&MyBuffer[sockindex][8], (Recv_len[sockindex] - 8), &MyBuffer[sockindex][4], port, sockindex);
      Recv_len[sockindex] = 0;
    }
  }
}
//------------------------------------------------------------------------------

//--------------------------------Public Func-----------------------------------
void eth_init(void)
{
  uint8_t  res;
  
  res = CH395CMDGetVer();   //0x4A
  sprintf(ntxbuf, "CH395VER : 0x%2X\r\n", res);
  _tx_data(ntxbuf, strlen(ntxbuf));
    
  mcu_delay_ms(20);         //must be 0x9A
  res = CH395CMDCheckExist(0x65);
  sprintf(ntxbuf, "Exist : 0x%2X\r\n", res);
  _tx_data(ntxbuf, strlen(ntxbuf));
  
  _InitCH395InfParam();
  
  CH395CMDSetIPAddr(CH395Inf.IPAddr);     /* Set CH395 IP */
  CH395CMDSetGWIPAddr(CH395Inf.GWIPAddr); /* Set GW IP */
  CH395CMDSetMASKAddr(CH395Inf.MASKAddr); /* Set MASK */
  res = CH395CMDInitCH395();  //0--OK
  sprintf(ntxbuf, "Init result : 0x%2X\r\n", res);
  _tx_data(ntxbuf, strlen(ntxbuf));
}

void eth_cyc(void)
{
  if(CH395CMDGetPHYStatus() == PHY_DISCONN){ /* Example Query whether the CH395 is connected */
    mcu_delay_ms(200);
  }
  
  _InitSocketParam(); /* Initialize socket related variables */
  _SocketInitOpen();
  
  while(1){
    if(_Query395Interrupt() == 0){
      CH395GlobalInterrupt();
    }
    UDP_Server_Data_Loop(0);
  }
}
//------------------------------------EOF---------------------------------------

